package com.syyo.admin.common.aspect;


import com.syyo.admin.common.anno.SysLog;
import com.syyo.admin.domain.entity.LogEntity;
import com.syyo.admin.service.LogService;
import com.syyo.admin.utils.MyStringUtils;
import com.syyo.admin.utils.SecurityUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.time.LocalDateTime;

/**
 * @Auther: wangzhong
 * @Date: 2019/10/11 11:42
 * @Description: 记录系统操作日志, 使用这个，所有接口只能有一个参数
 */
@Aspect
@Component
public class LogAspect {

    @Autowired
    private LogService logService;

    ThreadLocal<Long> currentTime = new ThreadLocal<>();

    /**
     * 配置切入点
     */
    @Pointcut("@annotation(com.syyo.admin.common.anno.SysLog)")
    public void logPointcut() {
    }


    @Around("logPointcut()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        // 执行方法
        Object proceed;
        currentTime.set(System.currentTimeMillis());
        proceed = pjp.proceed();
        long elapsedTime = System.currentTimeMillis() - currentTime.get();
        currentTime.remove();
        String logType = "info";
        String errorMsg = "";
        //记录日志
        saveSysLog(pjp, logType, errorMsg, elapsedTime);
        return proceed;
    }

    /**
     * 配置异常通知
     *
     * @param
     * @param
     */
    @AfterThrowing(pointcut = "logPointcut()", throwing = "e")
    public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
        ProceedingJoinPoint pjp = (ProceedingJoinPoint) joinPoint;
        if (currentTime.get() != null) {
            long elapsedTime = System.currentTimeMillis() - currentTime.get();
            currentTime.remove();
            String logType = "error";
            String errorMsg = e.getMessage();
            saveSysLog(pjp, logType, errorMsg, elapsedTime);
        }
    }

    /**
     * 保存数据库
     *
     * @param
     * @param
     */
    private void saveSysLog(ProceedingJoinPoint pjp, String logType, String errorMsg, long elapsedTime) {
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method method = signature.getMethod();
        SysLog annotation = method.getAnnotation(SysLog.class);
        String title = annotation.value();
        //请求的方法名
        String className = pjp.getTarget().getClass().getName();
        String methodName = signature.getName();
        String methodNameFull = className + "." + methodName + "()";
        //请求的参数
        String param = "";
        Object[] args = pjp.getArgs();
        if (args != null && args.length > 0) {
//            param = JSON.toJSONString(args[0]); //不是json参数会报错
            param = args[0] + "";
        }

        //获取request
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String ip = MyStringUtils.getIp(request);
        String browser = MyStringUtils.getBrowser(request);
        String username = SecurityUtils.getUsername();
        LocalDateTime now = LocalDateTime.now();
        LogEntity log = new LogEntity();
        log.setUserName(username);
        log.setContent(param);
        log.setCreateTime(now);
        log.setIp(ip);
        log.setTitle(title);
        log.setMethod(methodNameFull);
        log.setLogType(logType);
        log.setErrorMsg(errorMsg);
        log.setElapsedTime(elapsedTime);
        log.setBrowser(browser);
        logService.add(log);
    }
}
